home *** CD-ROM | disk | FTP | other *** search
/ SPACE 2 / SPACE - Library 2 - Volume 1.iso / apps / 25 / demos / levy.c < prev    next >
Encoding:
C/C++ Source or Header  |  1986-06-19  |  18.7 KB  |  635 lines

  1. /*
  2.  * levy.ttp:  Brownian Relief Fractal Generation Program for the Atari 520ST
  3.  *
  4.  * This program is distributed in the public domain with no restrictions on
  5.  * its use.
  6.  *
  7.  * The algorithm implemented herein is described in B. B. Mandelbrot "Fractals:
  8.  * Form, Chance, and Dimension" (Freeman 1977) p. 207. It was first defined
  9.  * by P. Levy "Processus Stochastiques et Mouvement Brownien" (Paris:
  10.  * Gauthier-Villars 1948).
  11.  *
  12.  * program author: J. M. Knapp  AT&T Bell Labs   Columbus OH  (cbosgd!nscs!jmk)
  13.  *
  14.  * Background (from Mandelbrot):
  15.  *
  16.  * [The Brownian model of the landscape] finally provides us with our
  17.  * long-sought example of a curve that (a) is devoid of self intersections,
  18.  * (b) is practically devoid of self contacts, (c) has fractal dimension
  19.  * clearly greater than 1, and (d) is isotropic.
  20.  *
  21.  * More precisely, the dimension of these coastlines is 3/2, which is of
  22.  * course much higher than most of Richardson's values [e.g. 1.26 for the
  23.  * coast of Britain]. The Brownian artificial coastline is therefore
  24.  * limited in its applicability. It recalls northern Canada, Indonesian
  25.  * Islands, perhaps western Scotland, and the Aegean. It is applicable to
  26.  * other examples as well, but certainly not to all.
  27.  *
  28.  * It is a pity, because a relief of dimension D=5/2 and coastlines of
  29.  * dimension 3/2 would have been easy to explain. Indeed, the Brown-Levy
  30.  * function is an excellent approximation of the relief that would have
  31.  * been created by superimposing independent rectilinear faults.  The
  32.  * generative model proceeds simply as follows. Starting with a horizontal
  33.  * plateau, break it along a straight line chosen at random to introduce
  34.  * a kind of cliff, a random difference between the levels of the two
  35.  * sides of the break. Then start all over again, ad infinitum. The
  36.  * process merely generalizes the Poisson process. With no need for
  37.  * mathematical or physical details, we can see that the argument seizes
  38.  * at least one aspect of tectonic evolution...
  39.  *
  40.  * From B.B. Mandelbrot "Fractals: Form, Chance, and Dimension"
  41.  * 
  42.  */
  43.  
  44. #include <stdio.h>
  45. #include <math.h>
  46. #include <fcntl.h>
  47.  
  48. /* PUT YOUR ST HEADER FILES HERE */
  49. /* the following are Lattice C header files */
  50. #include <gemlib.h>
  51. #include <osbind.h>
  52.  
  53. #define TRUE  1
  54. #define FALSE 0
  55.  
  56. #define NX     320           /* max number of horizontal pixels */
  57. #define NY     200           /* max number of vertical pixels */
  58. #define NCOLOR  15           /* number of colors excluding background */
  59. #define GRMODE   0           /* graphics mode 0 (320x200) */
  60. #define SAVEFILE "levy.pi1"  /* DEGAS default save-file */
  61. #define FSIZE  32034         /* size of DEGAS save-file */
  62.  
  63. #define SEED   2211955       /* default pseudorandom seed */
  64.  
  65. /* help */
  66. #define US0 "TTP parameter usage:\n\n"
  67. #define US1 "number of iterations:\n"
  68. #define US1a "   -n<N> must always be specified\n\n"
  69. #define US2 "optionally [default values in ()]:\n"
  70. #define US3 "-s<int> sets random seed (2211955)\n"
  71. #define US4 "-x<1-320> # of horizontal pixels (320)\n"
  72. #define US5 "-y<1-200> # of vertical pixels (200)\n"
  73. #define US6 "-u<N> update screen every N iterations\n"
  74. #define US7 "      (default: only update when done)\n"
  75. #define US8 "-f<filename> save-file name (levy.pi1)\n"
  76. #define US9 "-d<file> display previously-stored file\n"
  77. #define US9a "-i to generate island-dominated relief\n\n"
  78. #define US10 "examples:\n"
  79. #define US11 "   -n10000 -i\n"
  80. #define US12 "   -n100 -s9349490390 -fcoast.pi1\n"
  81. #define US13 "   -dcoast.pi1\n\n"
  82. #define US14 "press any key to abort run in progress\n\n"
  83.  
  84. /* VDI globals */
  85. short contrl[12],
  86.       intin[128],
  87.       intout[128],
  88.       ptsin[128],
  89.       ptsout[128] ;
  90.  
  91. short oldpalette[16] ;   /* storage for old palette */
  92.  
  93. /*************/
  94. main(argc,argv) 
  95. int argc ;
  96. char *argv[] ;
  97. {
  98.  
  99.    short *relief ;   /* pointer to 'relief' data structure */
  100.    long ncyc ;       /* number of iterations of generation process */
  101.    long iseed ;      /* pseudorandom seed */
  102.    int xl, yl ;      /* extent of each axis of screen region */
  103.    short handle ;    /* VDI screen handle */
  104.    short update ;    /* screen update every 'update' iterations */
  105.    char fname[80] ;  /* save-file */
  106.    short loadf ;     /* load flag: if true then load & display pic */
  107.    short island ;    /* if true --> generate island-dominated relief */
  108.  
  109.    /* VDI palette (increasing altitude) */
  110.    static short palette[NCOLOR+1] = { 0x000, 0x003, 0x004, 0x005,
  111.                                       0x660, 0x550, 0x440, 0x340,
  112.                                       0x040, 0x050, 0x432, 0x543,
  113.                                       0x653, 0x444, 0x555, 0x777 } ;
  114.  
  115.    short xpalette[NCOLOR+1] ;  /* palette xlated to VDI ordering */
  116.  
  117.    short cginit(), cgopen() ;
  118.  
  119.    /* begin */
  120.    conflush() ;   /* clear console input buffer */
  121.  
  122.    /* process argv[] options */
  123.    options(argc,argv,&xl,&yl,&ncyc,&iseed,&update,fname,&loadf,&island) ;
  124.  
  125.    if (loadf)  /* load and display DEGAS file */
  126.    {
  127.       handle = cginit(palette,xpalette) ;   /* open screen */
  128.       if (readfrac(fname,palette) < 0)      /* send file data to physbase */
  129.       {
  130.          gemdos(0x1) ;                      /* PAKTC */
  131.          cgclose(handle) ;                  /* file read error */
  132.          exit(1) ;
  133.       }
  134.       Setpallette(palette) ;                /* set new palette */
  135.       gemdos(0x1) ;                         /* PAKTC */
  136.       cgclose(handle) ;                     /* done, restore screen */
  137.       exit(0) ;
  138.    }
  139.  
  140.    /* generate new relief */
  141.  
  142.    srand48(iseed) ;  /* randomize */
  143.  
  144.    /* allocate 'relief' data structure */
  145.    if((relief = (short *)malloc(sizeof(short)*xl*yl)) == 0)
  146.    {
  147.       fprintf(stderr,"Not enough memory\n") ;
  148.       gemdos(0x1) ;  /* PAKTC */
  149.       exit(1) ;
  150.    }
  151.  
  152.    level(relief,xl,yl) ;  /* initialize to level 'plain' */
  153.  
  154.    handle = cginit(palette,xpalette) ;  /* initialize graphics device */
  155.  
  156.    if (cycle(handle,relief,xl,yl,ncyc,update,island))  /* generate relief */
  157.    {
  158.       plotrel(handle,relief,xl,yl,island) ;            /* plot relief */
  159.       gemdos(0x1) ;
  160.    }
  161.  
  162.    if (writefrac(fname,xpalette) < 0)  /* save screen to DEGAS file */
  163.    {
  164.       gemdos(0x1) ;
  165.       cgclose(handle) ;    /* file write error, clean up & quit */
  166.       exit(1) ;
  167.    }
  168.    cgclose(handle) ;                   /* close graphics device */
  169.  
  170.    exit(0) ;     /* done */
  171. }
  172.  
  173. /* fractal generation routine */
  174. int cycle(handle,relief,xl,yl,ncyc,update,island)
  175. short handle ;
  176. short *relief ;
  177. int xl, yl ;
  178. long ncyc ;
  179. short update ;
  180. short island ;
  181. {
  182.    int icyc ;  /* cycle counter */
  183.  
  184.    printf("working...\n") ;
  185.    for (icyc = 0 ; icyc < ncyc ; icyc++)
  186.    {
  187.       if (drand48() < .5)            /* either inc or dec half-plane */
  188.          inc_hplane(relief,xl,yl) ;
  189.       else
  190.          dec_hplane(relief,xl,yl) ;
  191.  
  192.       if (update && icyc && !(icyc % update))
  193.          plotrel(handle,relief,xl,yl,island) ;  /* update screen */
  194.  
  195.       if (Bconstat(2))
  196.       {
  197.          conflush() ;  /* a key was pressed, flush and abort */
  198.          return(FALSE) ;
  199.       }
  200.    }
  201.    return(TRUE) ;
  202. }
  203.  
  204. /* increment half-plane */
  205. inc_hplane(relief,xl,yl)
  206. short *relief ;
  207. int xl, yl ;
  208. {
  209.    register short *endcolp, *ap ;  /* end-of-column pointer, array pointer */
  210.    register short iy, ryl ;        /* row index, reg yl holder */
  211.    int m, b ;                      /* slope & intercept of random line */
  212.  
  213.    ryl = yl ;             /* put yl in register */
  214.    rndmb(xl,yl,&m,&b) ;   /* get random line parameters m & b */
  215.  
  216.    ap = relief + yl * (xl - 1) ;  /* point to beginning of last column */
  217.    endcolp = ap + yl ;            /* point to end of last column */
  218.  
  219.    /* increment all elements below  random line */
  220.    while (xl--)  /* for all columns */
  221.    {
  222.       iy = ((m * xl) >> 8) + b ;  /* starting y-value to increment */
  223.       if(iy < 0) iy = 0 ;         /* can't start before 0th element! */
  224.       if (iy < yl)                /* no action if past last element in col */
  225.       {
  226.          ap += iy ;                  /* point to 1st value to inc */
  227.          while(ap < endcolp)         /* increment rest of column */
  228.             (*(ap++))++ ;
  229.          endcolp -= ryl ;            /* point to end of previous column */
  230.          ap -= (ryl << 1) ;          /* point to beginning of previous column */
  231.       }
  232.       else
  233.       {
  234.          ap -= ryl ;          /* point to end of previous column */
  235.          endcolp -= ryl ;     /* point to beginning of previous column */
  236.       }
  237.    }   
  238. }
  239.  
  240. /* decrement half-plane */
  241. dec_hplane(relief,xl,yl)
  242. short *relief ;
  243. int xl, yl ;
  244. {
  245.    register short *endcolp, *ap ;  /* end-of-column pointer, array pointer */
  246.    register short iy, ryl ;        /* row index, reg yl holder */
  247.    int m, b ;                      /* slope & intercept of random line */
  248.  
  249.    ryl = yl ;             /* put yl in register */
  250.    rndmb(xl,yl,&m,&b) ;   /* get random line parameters m & b */
  251.  
  252.    ap = relief + yl * (xl - 1) ;  /* point to beginning of last column */
  253.    endcolp = ap + yl ;            /* point to end of last column */
  254.  
  255.    /* decrement all elements to right of random line */
  256.    while (xl--)  /* for all columns */
  257.    {
  258.       iy = ((m * xl) >> 8) + b ;  /* starting y-value to decrement */
  259.       if(iy < 0) iy = 0 ;         /* can't start before 0th element! */
  260.       if (iy < yl)                /* no action if past last element in col */
  261.       {
  262.          ap += iy ;                  /* point to 1st value to dec */
  263.          while(ap < endcolp)         /* decrement rest of column */
  264.             (*(ap++))-- ;
  265.          endcolp -= ryl ;            /* point to end of previous column */
  266.          ap -= (ryl << 1) ;          /* point to beginning of previous column */
  267.       }
  268.       else
  269.       {
  270.          ap -= ryl ;          /* point to end of previous column */
  271.          endcolp -= ryl ;     /* point to beginning of previous column */
  272.       }
  273.    }   
  274. }
  275.  
  276. /* set all elements to 0 (level plane) */
  277. level(relief,xl,yl)
  278. short *relief ;
  279. int xl, yl ;
  280. {
  281.    register short *ap, *endp ;   /* array pointer, end pointer */
  282.  
  283.    ap = relief ;
  284.    endp = relief + xl*yl ;
  285.    while (ap < endp)
  286.       *(ap++) = 0 ;
  287. }
  288.  
  289. /* return slope (m) and intercept (b) of random line through plane */
  290. /* (slope is scaled by 256) */
  291. rndmb(xl,yl,m,b)
  292. int xl, yl ;
  293. int *m, *b ;
  294. {
  295.    float dx, dy ;  /* delta-x, delta-y */
  296.    int x0, y0 ;  /* random point on plane */
  297.    double drand48() ;
  298.  
  299.    dx = 0 ; dy = 0 ;
  300.    while((dx = 2.0*drand48() - 1.0) == 0) ; /* prevent division by 0 */
  301.    dy = drand48() ;
  302.    x0 = xl*drand48() ;
  303.    y0 = yl*drand48() ;       /* (x0,y0) random point */
  304.  
  305.    *m = (256.0*dy)/dx ;
  306.    *b =  y0 - (*m*x0)/256 ;     /* calculate y-intercept */
  307. }
  308.  
  309. /* initialize screen device */
  310. short cginit(palette,xpalette)
  311. short *palette, *xpalette ;
  312. {
  313.    /* translation from color index to palette index  PI = ctrans[CI] */
  314.    static short ctrans[NCOLOR+1] =
  315.       { 0, 2, 3, 6, 4, 7, 5, 8, 9, 10, 11, 14, 12, 15, 13, 1 } ;
  316.    short colind ;     /* color index */
  317.    short handle ;     /* screen handle */
  318.    short cgopen() ;
  319.  
  320.    handle = cgopen() ;
  321.  
  322.    /* save old palette */
  323.    for (colind = 0 ; colind < NCOLOR+1 ; colind++)
  324.       oldpalette[colind] = Setcolor(colind,-1) ;
  325.  
  326.    /* initialize color look-up table */
  327.    for (colind = 0 ; colind < NCOLOR+1 ; colind++)
  328.       xpalette[colind] = palette[ctrans[colind]] ;
  329.    Setpallette(xpalette) ;
  330.  
  331.    return(handle) ;
  332. }
  333.  
  334. /* plot relief */
  335. plotrel(handle,relief,xl,yl,island)
  336. short handle ;
  337. short *relief ;
  338. int xl, yl ;
  339. short island ;
  340. {
  341.    int iy, ix, icol ;   /* row index, column index, color index */
  342.    short minval, maxval ;  /* min, max altitude */
  343.    register short *ap ;    /* array pointer */
  344.  
  345.    /* extents of color regions (increasing altitude): */
  346.  
  347.    /* continental relief */
  348.    static float cext_con[NCOLOR+1] = { 0, .15, .25, .35,
  349.                                           .40, .45, .50,
  350.                                           .55, .65, .70,
  351.                                           .75, .80, .85,
  352.                                           .90, .95, 1.00 } ;
  353.  
  354.    /* island relief */
  355.    static float cext_ile[NCOLOR+1] = { 0, .30, .55,  .65,
  356.                                           .68, .71,  .74,
  357.                                           .77, .85,  .88,
  358.                                           .91, .93,  .95,
  359.                                           .97, .99, 1.00 } ;
  360.  
  361.    float *cext ;
  362.  
  363.    /* integer (absolute altitude) extents of color regions */
  364.    short icext[NCOLOR+1] ;
  365.  
  366.    /* set extents pointer */
  367.    if (island)
  368.       cext = cext_ile ;
  369.    else
  370.       cext = cext_con ;
  371.  
  372.    minmax(relief,xl,yl,&maxval,&minval) ;  /* find max and min altitude */
  373.  
  374.    /* calculate integer extents */
  375.    for (icol = 0 ; icol < NCOLOR+1 ; icol++)
  376.       icext[icol] = minval + cext[icol] * (maxval - minval) ;
  377.  
  378.    icext[NCOLOR]++ ;  /* tricky: bump last value by one */
  379.  
  380.    ap = relief ;  /* point to beginning */
  381.    for (ix= 0 ; ix < xl ; ix++)  /* for all columns */
  382.    {
  383.       register short colm[NY] ;  /* color indices for screen column */
  384.       for (iy = 0 ; iy < yl ; iy++)   /* for all rows */
  385.       {
  386.          register short *cp, colind ;  /* color pointer, color index */
  387.          cp = icext ;                  /* point to color region 0 */
  388.          colind = 0 ;
  389.          while(*ap >= *(cp++)) colind++ ;
  390.          colm[iy] = colind ;
  391.          ap++ ;
  392.       }
  393.       column(handle,colm,ix,yl) ;  /* plot column */
  394.    }
  395. }
  396.  
  397. /* find maximum & minimum values of altitude */
  398. minmax(relief,xl,yl,maxval,minval)
  399. short *relief ;
  400. int xl, yl ;
  401. short *maxval, *minval ;
  402. {
  403.    register short *ap, *endp ;   /* array pointer, end pointer */
  404.  
  405.    *maxval = *relief ; *minval = *relief ;
  406.    ap = relief ;
  407.    endp = ap + xl*yl ;
  408.    while (ap < endp)
  409.    {
  410.       if (*ap > *maxval) *maxval = *ap ;
  411.       if (*ap < *minval) *minval = *ap ;
  412.       ap++ ;
  413.    }
  414. }
  415.  
  416. /* flush any characters in console input buffer */
  417. conflush()
  418. {
  419.    char ch ;
  420.    while(Bconstat(2))
  421.       ch = Bconin(2) ;
  422. }
  423.  
  424. /* process argv options */
  425. options(argc,argv,xl,yl,ncyc,iseed,update,fname,loadf,island)
  426. int argc ;
  427. char *argv[] ;
  428. int *xl, *yl ;
  429. long *ncyc ;
  430. long *iseed ;
  431. short *update ;
  432. char *fname ;
  433. short *loadf ;
  434. short *island ;
  435. {
  436.    int help ;
  437.    int optind ;
  438.  
  439.    /* set defaults */
  440.    help = FALSE ;
  441.    *iseed = SEED ;
  442.    *ncyc = 0 ;
  443.    *xl = NX ;
  444.    *yl = NY ;
  445.    *update = 0 ;
  446.    sprintf(fname,"%s",SAVEFILE) ;
  447.    *loadf = FALSE ;
  448.    *island = FALSE ;
  449.  
  450.    optind = 1 ;
  451.    while ((optind < argc) && (*argv[optind] == '-'))
  452.    {
  453.       switch(*(argv[optind]+1))
  454.       {
  455.          case 's':
  456.          case 'S':
  457.            *iseed = atol(argv[optind]+2);
  458.            break;
  459.  
  460.          case 'n':
  461.          case 'N':
  462.            *ncyc = atol(argv[optind]+2);
  463.            break;
  464.  
  465.          case 'u':
  466.          case 'U':
  467.             *update = atoi(argv[optind]+2) ;
  468.             break ;
  469.  
  470.          case 'f':
  471.          case 'F':
  472.             sprintf(fname,"%s",argv[optind]+2) ;
  473.             break ;
  474.  
  475.          case 'd':
  476.          case 'D':
  477.             sprintf(fname,"%s",argv[optind]+2) ;
  478.             *loadf = TRUE ;
  479.             break ;
  480.  
  481.          case 'y':
  482.          case 'Y':
  483.            *yl = atoi(argv[optind]+2) ;
  484.            break ;
  485.  
  486.          case 'x':
  487.          case 'X':
  488.            *xl = atoi(argv[optind]+2) ;
  489.            break ;
  490.  
  491.          case 'i':
  492.          case 'I':
  493.             *island = TRUE ;
  494.             break ;
  495.  
  496.          default:
  497.            help = TRUE ;
  498.            break ;
  499.       }
  500.       optind += 1 ;
  501.    }
  502.  
  503.    if((optind != argc) || (argc == 1 )) help = TRUE ;
  504.  
  505.    if( help )
  506.    {
  507.       fprintf(stderr,"%s", US0);
  508.       fprintf(stderr,"%s", US1);
  509.       fprintf(stderr,"%s", US1a) ;
  510.       fprintf(stderr,"%s", US2);
  511.       fprintf(stderr,"%s", US3);
  512.       fprintf(stderr,"%s", US4);
  513.       fprintf(stderr,"%s", US5);
  514.       fprintf(stderr,"%s", US6);
  515.       fprintf(stderr,"%s", US7);
  516.       fprintf(stderr,"%s", US8);
  517.       fprintf(stderr,"%s", US9);
  518.       fprintf(stderr,"%s", US9a) ;
  519.       fprintf(stderr,"%s", US10);
  520.       fprintf(stderr,"%s", US11);
  521.       fprintf(stderr,"%s", US12);
  522.       fprintf(stderr,"%s", US13);
  523.       fprintf(stderr,"%s", US14) ;
  524.       fprintf(stderr,"press any key to continue") ;
  525.       gemdos(0x1) ;
  526.       exit(1);
  527.    }
  528. }
  529.  
  530. /* close graphics screen and enable cursors */
  531. cgclose(handle)
  532. short handle ;
  533. {
  534.    v_show_c(handle) ;
  535.    Cursconf(1,0) ;
  536.    Setpallette(oldpalette) ;
  537.    v_clsvwk(handle) ;
  538.    appl_exit() ;
  539. }
  540.  
  541. /* open graphics screen and disable cursors */
  542. short cgopen()
  543. {
  544.    short handle ;
  545.    short work_in[12],
  546.          work_out[57] ;
  547.    int iwk, set_type ;
  548.  
  549.    appl_init() ;
  550.  
  551.    for (iwk = 0 ; iwk < 10 ; work_in[iwk++] = 1) ;
  552.    work_in[10] = 2 ; /* raster coordinates */
  553.  
  554.    v_opnvwk(work_in,&handle,work_out) ;
  555.    v_hide_c(handle) ;  /* bye mouse */
  556.    Cursconf(0,0) ;     /* bye cursor */
  557.    v_clrwk(handle) ;   /* clear screen */
  558.    set_type = vsm_type(handle,1) ;  /* marker type = point */
  559.    return(handle) ;
  560. }
  561.  
  562. /* plot column on graphics screen */
  563. column(handle,colm,ix,npoints)
  564. short handle ;
  565. register short *colm ;
  566. int ix ;
  567. int npoints ;
  568. {
  569.    register short pxy[2] ;
  570.  
  571.    *pxy = ix ;
  572.    *(pxy+1) = npoints ;
  573.    while((*(pxy+1))--)
  574.    {
  575.       vsm_color(handle,colm[*(pxy+1)]) ;
  576.       v_pmarker(handle,1,pxy) ;
  577.    }
  578. }
  579.  
  580. /* save screen data to disk in DEGAS format */
  581. int writefrac(fname,palette) 
  582. char *fname ;
  583. short *palette ;
  584. {
  585.    char *scrnp ;
  586.    int fd, n ;
  587.    short gmode[1] ;
  588.  
  589.    scrnp = (char *)Physbase() ;  /* get pointer to display frame */
  590.    *gmode = GRMODE ;
  591.  
  592.    if ((fd = open(fname, O_RAW | O_CREAT | O_WRONLY)) < 0) {
  593.       fprintf(stderr,"open of '%s' failed\n",fname) ;
  594.       return(-1) ;
  595.       }
  596.  
  597.    n = write(fd, gmode, 2) ;      /* write graphics mode */
  598.    n += write(fd, palette, 32) ;  /* write palette */
  599.    if ((n += write(fd, scrnp, 32000)) != FSIZE)  /* write screen */
  600.    {
  601.       fprintf(stderr,"file write error: only %d bytes written\n",n) ;
  602.       close(fd) ;
  603.       return(-1) ;
  604.    }
  605.    close(fd) ;
  606.    return(0) ;
  607. }
  608.  
  609. /* read file (DEGAS format) */
  610. int readfrac(fname,palette)
  611. char *fname ;
  612. short *palette ;
  613. {
  614.    int fd, n ;
  615.    short gmode[1] ;
  616.    char *scrnp ;
  617.  
  618.    if ((fd = open(fname, O_RAW | O_RDONLY)) < 0) {
  619.       fprintf(stderr,"open of '%s' failed\n",fname) ;
  620.       return(-1) ;
  621.       }
  622.  
  623.    scrnp = (char *)Physbase() ;
  624.    n = read(fd, gmode, 2) ;      /* read graphics mode */
  625.    n += read(fd, palette, 32) ;  /* read palette */
  626.    if ((n += read(fd, scrnp, 32000)) != FSIZE)  /* read screen */
  627.    {
  628.       fprintf(stderr,"file write error: only %d bytes read\n",n) ;
  629.       close(fd) ;
  630.       return(-1) ;
  631.    }
  632.    close(fd) ;
  633.    return(0) ;
  634. }
  635.